package cn.b.sky.mes.qm.service.impl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import cn.b.sky.mes.qm.model.condition.InspectRecordCondition;
import cn.b.sky.mes.qm.service.InspectRecordService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.b.sky.mes.cm.enums.OperationType;
import cn.b.sky.mes.cm.model.ProcessInspectPicture;
import cn.b.sky.mes.cm.model.ProcessOperation;
import cn.b.sky.mes.cm.model.WorkCenter;
import cn.b.sky.mes.cm.service.ProcessService;
import cn.b.sky.common.model.TreeInterface;
import cn.b.sky.common.utils.FTPUtils;
import cn.b.sky.common.utils.SkyFileUtils;
import cn.b.sky.common.utils.MathUtils;
import cn.b.sky.common.utils.SpringBeanUtil;
import cn.b.sky.common.utils.TreeUtil;
import cn.b.sky.user.model.Attachment;
import cn.b.sky.user.service.AttachmentService;
import cn.b.sky.mes.qm.constants.QmConstant;
import cn.b.sky.mes.qm.dao.DefectDao;
import cn.b.sky.mes.qm.dao.InspectRecordDao;
import cn.b.sky.mes.qm.model.Defect;
import cn.b.sky.mes.qm.model.DefectInspectRecord;
import cn.b.sky.mes.qm.model.DefectNode;
import cn.b.sky.mes.qm.model.DefectProcessOperation;
import cn.b.sky.mes.qm.model.DefectTopN;
import cn.b.sky.mes.qm.model.InspectRecord;
import cn.b.sky.mes.qm.model.InspectRecordAttachment;
import cn.b.sky.mes.qm.model.OperationDefectCount;
import cn.b.sky.mes.qm.model.UserDefect;

@Service("inspectRecordService")
public class InspectRecordServiceImpl implements InspectRecordService {
  private static final Logger LOG = LoggerFactory.getLogger(InspectRecordServiceImpl.class);

  @Autowired
  private InspectRecordDao inspectRecordDao;

  @Resource
  private ProcessService processService;

  @Resource
  AttachmentService attachmentService;

  @Autowired
  private DefectDao defectDao;

  @Override
  public List<InspectRecord> getInspectRecordsByCondition(InspectRecordCondition condition) {
    if (condition == null) {
      condition = new InspectRecordCondition();
    }
    if (StringUtils.isBlank(condition.getOrderField())) {
      condition.setOrderField("createDateTime");//默认创建时间
    }

    return inspectRecordDao.selectInspectRecordsByCondition(condition);
  }

  @Override
  public int getInspectRecordCountByCondition(InspectRecordCondition condition) {
    if (condition == null) {
      condition = new InspectRecordCondition();
    }
    return inspectRecordDao.selectInspectRecordCountByCondition(condition);
  }

  @Override
  public InspectRecord getInspectRecordById(Long id) {
    if (null != id) {
      return inspectRecordDao.selectInspectRecordById(id);
    }
    return null;
  }

  @Override
  public List<InspectRecordAttachment> getInspectRecordAttachment(Long id) {
    if (null != id) {
      return inspectRecordDao.selectInspectRecordAttachmentsByInspectRecordId(id);
    }
    return null;
  }

  @Override
  public List<DefectTopN> getDefectTopNData(InspectRecordCondition condition) {
    if (condition == null) {
      return null;
    }
    List<DefectTopN> tops = inspectRecordDao.selectDefectTopnData(condition);
    Integer count = inspectRecordDao.selectDefectTotalData(condition);
    int topCount = 0;
    //topN的缺陷代码，区分其他使用
    String defectCode = "";
    //top数量小于或等于查询的数量
    if (tops != null && count != null && tops.size() <= condition.getNumPerPage()) {
      for (DefectTopN top : tops) {
        Defect defect = defectDao.getDefect(top.getDefectCode(), condition.getSiteCode());
        if (defect == null) {
          continue;
        }
        top.setDefectText(defect.getDefectText());
        top.setDefectLevelText(defect.getDefectLevelText());
        top.setDefectTypeText(defect.getDefectTypeText());
        top.setResponsibilityTypeText(defect.getResponsibilityTypeText());
        topCount += top.getDefectCount();
        defectCode += "'" + top.getDefectCode() + "'";
        defectCode += ",";
        //百分比
        top.setPercent(MathUtils.getPercent(top.getDefectCount(), count));
      }
      //其他的缺陷
      if (topCount < count) {
        DefectTopN otherDefect = new DefectTopN();
        otherDefect.setDefectCode(defectCode + "'" + QmConstant.TOPN_OTHER + "'");
        otherDefect.setDefectText("其他");
        otherDefect.setDefectCount(count - topCount);
        otherDefect.setPercent(MathUtils.getPercent(otherDefect.getDefectCount(), count));
        tops.add(otherDefect);
      }
      //总数
      DefectTopN totalDefect = new DefectTopN();
      totalDefect.setDefectCode(QmConstant.TOPN_TOTAL);
      totalDefect.setDefectText("总计");
      totalDefect.setDefectCount(count);
      totalDefect.setPercent("100%");
      tops.add(totalDefect);
    }
    return tops;
  }

  @Override
  public List<DefectInspectRecord> selectDefectInspectRecords(DefectProcessOperation operation) {
    return inspectRecordDao.selectDefectInspectRecords(operation);
  }

  @Override
  public List<ProcessOperation> selectQmOperation(String siteCode, String processCode, String processrev) {
    return processService.selectProcessOperationsForDefectGraph(siteCode, processCode, processrev,
        OperationType.QUALITY, null);
  }

  @Override
  public List<TreeInterface> getDefectNodeTreeWithColor(String siteCode) {
    if (StringUtils.isBlank(siteCode)) {
      return null;
    }
    List<DefectNode> nodes = inspectRecordDao.selectDefectNodeTreeWithColor(siteCode);
    return TreeUtil.gradingRecursion(nodes.toArray(new DefectNode[nodes.size()]), null);
  }

  @Override
  public List<UserDefect> selectUserDefects(String siteCode, String userCode, String operationCode, boolean isOnlyPic) {
    return inspectRecordDao.selectUserDefects(siteCode, userCode, operationCode, isOnlyPic);
  }

  @Override
  public void insertUserDefect(UserDefect userDefect) {
    if (inspectRecordDao.selectUserDefect(userDefect) == null) {
      inspectRecordDao.insertUserDefect(userDefect);
    }

  }

  @Override
  public void deleteUserDefect(UserDefect userDefect) {
    inspectRecordDao.deleteUserDefect(userDefect);

  }

  @Override
  public void insertInspectRecords(List<InspectRecord> inspectRecordList) {
    for (InspectRecord inspectRecord : inspectRecordList) {
      inspectRecord.setCreateDateTime(new Date());
      inspectRecord.setModifyDateTime(new Date());
      inspectRecordDao.insertInspectRecord(inspectRecord);
      OperationDefectCount oc = new OperationDefectCount();
      oc.setSiteCode(inspectRecord.getSiteCode());
      oc.setOperationCode(inspectRecord.getOperationCode());
      oc.setDefectCode(inspectRecord.getDefectCode());
      OperationDefectCount oldOc = inspectRecordDao.selectOperationDefectCount(oc);
      if (oldOc != null) {
        oc.setCount(oldOc.getCount() + 1f);
        inspectRecordDao.updateOperationDefectCount(oc);
      } else {
        oc.setCount(1f);
        inspectRecordDao.insertOperationDefectCount(oc);
      }
      if (inspectRecord.getAttachments() != null && inspectRecord.getAttachments().size() > 0) {
        //新增附件
        for (InspectRecordAttachment recordAtt : inspectRecord.getAttachments()) {
          String saveName = UUID.randomUUID().toString();
          String filePath = SkyFileUtils.buildFilePath("inspectRecord");
          String md5 = "";
          md5 = SkyFileUtils.getMD5String(recordAtt.getFile());
          Attachment att = attachmentService.selectAttachmentByHashCode(inspectRecord.getSiteCode(), md5);
          if (att != null) {
            att.setRefCount(att.getRefCount() + 1);
            attachmentService.updateAttachmentRefCount(att);
            recordAtt.setAttachmentCode(att.getAttachmentCode());
          } else {
            InputStream file = new ByteArrayInputStream(recordAtt.getFile());
            String newFileName = SkyFileUtils.renameFileName(recordAtt.getFileName(), saveName);
            //创建多例的ftp，ftp上传需要多例
            FTPUtils ftpUtils = (FTPUtils) SpringBeanUtil.getBean("ftpUtils");
            String savePath = ftpUtils.uploadInputStream(file, filePath, newFileName);
            Attachment atachment = new Attachment();
            atachment.setSiteCode(inspectRecord.getSiteCode());
            atachment.setAttachmentCode(saveName);
            atachment.setSavePath(savePath);
            atachment.setFileName(recordAtt.getFileName());
            atachment.setFileSize(recordAtt.getFileSize());
            atachment.setHashCode(md5);
            atachment.setRefCount(1);
            attachmentService.insertAttachment(atachment);
            recordAtt.setAttachmentCode(saveName);
          }
          recordAtt.setInspectrecordId(inspectRecord.getId());
          inspectRecordDao.insertInspectRecordAttach(recordAtt);
        }
      }
    }

  }

  @Override
  public List<ProcessInspectPicture> getProcessInspectPictureByProcessOperation(int id) {
    List<ProcessInspectPicture> list = processService.getProcessInspectPictureByProcessOperation(id);
    if (list != null) {
      for (ProcessInspectPicture p : list) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
          ProcessInspectPicture pp = processService.getProcessInspectPictureByPk(p.getId());
          FTPUtils ftpUtils = (FTPUtils) SpringBeanUtil.getBean("ftpUtils");
          ftpUtils.fileDownload(pp.getSavePath(), os);
          p.setData(os.toByteArray());
          os.close();
        } catch (IOException e) {
          LOG.error("{}", e);
        }
      }
    }
    return list;
  }

  @Override
  public List<UserDefect> selectAllPicDefects(String siteCode, String operationCode) {
    return inspectRecordDao.selectAllPicDefects(siteCode, operationCode);
  }

  @Override
  public List<WorkCenter> getInspectRecordWorkCenters(InspectRecordCondition condition) {
    return inspectRecordDao.selectInspectRecordWorkCenters(condition);
  }

}
